package controller

import (
	"gin-rkboot-sw/internal/common"
	"gin-rkboot-sw/internal/model/entity"
	"gin-rkboot-sw/internal/service"
	"github.com/gin-gonic/gin"
)

var (
	User = cUser{}
)

type cUser struct{}

// List handler
// @Summary get all users
// @Tags User
// @version 1.0
// @produce application/json
// @Success 200 {object} common.R
// @Router /v1/user [get]
func (c *cUser) List(ctx *gin.Context) {
	resp := common.NewResponseBuilder[[]entity.User](ctx)
	if res := service.User.List(); res.IsError() {
		resp.ErrorMessage(res.Error())
	} else {
		resp.Data(res.MustGet())
	}
	resp.Response()
}

// Detail handler
// @Summary get one user
// @Tags User
// @version 1.0
// @Param id path string true "user id"
// @produce application/json
// @Success 200 {object} common.R
// @Router /v1/user/{id} [get]
func (c *cUser) Detail(ctx *gin.Context) {
	resp := common.NewResponseBuilder[entity.User](ctx)
	id := ctx.Param("id")
	if res := service.User.Detail(id); res.IsError() {
		resp.ErrorMessage(res.Error())
	} else {
		resp.Data(res.MustGet())
	}
	resp.Response()
}

// Add handler
// @Summary add a user
// @Tags User
// @version 1.0
// @Param user body entity.User true "user"
// @produce application/json
// @Success 200 {object} common.R
// @Router /v1/user [post]
func (c *cUser) Add(ctx *gin.Context) {
	resp := common.NewResponseBuilder[any](ctx)
	var user entity.User
	err := ctx.Bind(&user)
	if err != nil {
		resp.ErrorMessage(err).Code(400).Response()
		return
	}
	service.User.Save(user).ToEither().ForEach(func(err error) {
		resp.ErrorMessage(err)
	}, func(_ any) {})
	resp.Response()
}

// Update handler
// @Summary update a user
// @Tags User
// @version 1.0
// @Param user body entity.User true "user"
// @produce application/json
// @Success 200 {object} common.R
// @Router /v1/user [put]
func (c *cUser) Update(ctx *gin.Context) {
	responseBuilder := common.NewResponseBuilder[any](ctx)
	var user entity.User
	err := ctx.Bind(&user)
	if err != nil {
		responseBuilder.ErrorMessage(err).Code(400).Response()
		return
	}
	service.User.Update(user).ToEither().ForEach(func(err error) {
		responseBuilder.ErrorMessage(err)
	}, func(_ any) {})
	responseBuilder.Response()
}

// Delete handler
// @Summary delete one user
// @Tags User
// @version 1.0
// @Param id path string true "user id"
// @produce application/json
// @Success 200 {object} common.R
// @Router /v1/user/{id} [delete]
func (c *cUser) Delete(ctx *gin.Context) {
	responseBuilder := common.NewResponseBuilder[any](ctx)
	id := ctx.Param("id")
	if res := service.User.Delete(id); res.IsOk() {
		responseBuilder.Response()
	} else {
		responseBuilder.ErrorMessage(res.Error()).Response()
	}
}
